package org.dreamwork.jasmine2.i18n;

import org.dreamwork.i18n.*;
import org.dreamwork.i18n.MissingResourceException;
import org.dreamwork.i18n.adapters.XMLResourceAdapter;
import org.dreamwork.util.FileInfo;
import org.dreamwork.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletContext;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.regex.Pattern;

/**
 * Created by IntelliJ IDEA.
 * User: seth.yang
 * Date: 12-10-19
 * Time: 上午10:18
 */
public class WebResourceManager extends AbstractResourceManager {
    private static final Logger logger = LoggerFactory.getLogger (WebResourceManager.class);
    private static final Pattern SPLITER = Pattern.compile ("[\\s,;|]");

    private ServletContext context;
    private String resourceBase;
    private Locale defaultLocale;


    public WebResourceManager (ServletContext context, Locale defaultLocale, String resourceBase) {
        this.context = context;
        this.defaultLocale = defaultLocale;
        this.resourceBase = resourceBase;
    }

    public void initResources () {
        String[] a = SPLITER.split (resourceBase);
        Map<String, Set<URL>> map = new HashMap<String, Set<URL>> ();
        for (String path : a) {
            if (StringUtil.isEmpty (path)) continue;
            path = path.trim ();
            try {
                loadResources (map, path, null);
            } catch (MalformedURLException ex) {
                logger.warn (ex.getMessage (), ex);
            }
        }
        try {
            for (String baseName : map.keySet ()) {
                Set<URL> set = map.get (baseName);
                URL[] urls = new URL[set.size ()];
                XMLResourceAdapter adapter = new XMLResourceAdapter (this, defaultLocale, set.toArray (urls));
                adapter.loadResources (baseName, defaultLocale);
                softCache.put (baseName, adapter);
                locales.addAll (adapter.getSupportedLocales ());
            }
        } catch (Exception ex) {
            throw new MissingResourceException (ex);
        }
    }

    /**
     * 根据给定的资源名称，返回特定的 IResourceAdapter 实现
     *
     * @param baseName 资源名称
     * @return 资源适配器
     */
    @Override
    protected IResourceAdapter createResourceAdapter (String baseName) {
        String[] a = SPLITER.split (resourceBase);
        Map<String, Set<URL>> map = new HashMap<String, Set<URL>> ();
        for (String path : a) {
            if (StringUtil.isEmpty (path)) continue;
            path = path.trim ();
            try {
                loadResources (map, path, baseName);
            } catch (MalformedURLException ex) {
                logger.warn (ex.getMessage (), ex);
            }
        }

        Set<URL> set = map.get (baseName);
        URL[] urls = new URL[set.size ()];
        try {
            return new XMLResourceAdapter (this, defaultLocale, set.toArray (urls));
        } catch (Exception ex) {
            throw new MissingResourceException (ex);
        }
    }

    private void addResource (Map<String, Set<URL>> map, String name, URL url) {
        Set<URL> set = map.get (name);
        if (set == null) {
            set = new HashSet<URL> ();
            map.put (name, set);
        }
        if (url != null && !set.contains (url))
            set.add (url);
    }

    private void loadResources (Map<String, Set<URL>> map, String parent, String baseName) throws MalformedURLException {
        Set urls = context.getResourcePaths (parent);
        if (urls != null) for (Object o : urls) {
            String name = o.toString ();
            if (name.endsWith (".xml")) {
                String groupName = FileInfo.getFileNameWithoutExtension (name);
                if (baseName != null) {
                    String resourceName = FileInfo.getFileNameWithoutExtension (name);
                    if (resourceName.equals (baseName)) {
                        addResource (map, baseName, context.getResource (name));
                    }
                } else
                    addResource (map, groupName, context.getResource (name));
            } else if (name.endsWith ("/")) {
                char[] buff = name.toCharArray ();
                int i = buff.length - 1;
                for (int j = 0; ;++ j) {
                    if (buff [-- i] == '/') {
                        String resourceName = new String (buff, i + 1, j);
                        if (LocaleUtil.isValidLocale (resourceName)) {
                            if (baseName != null)
                                addResource (map, baseName, context.getResource (name + baseName + ".xml"));
                            else
                                loadResources (map, name, null);
                        }
                        break;
                    }
                }
            }
        }
    }
}